From 23144c9e7812797ece6ffe464b6c638f32869164 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Fri, 12 Mar 2004 11:47:09 +0000 Subject: [PATCH] bitkeeper revision 1.786 (4051a33dlWQlrVd1OVpwmHvW8Lp8Zw) serial.h, serial.c, traps.c, pdb-stub.c: Fix serial-char receive for PDB. --- xen/arch/i386/pdb-stub.c | 17 +--------- xen/arch/i386/traps.c | 14 -------- xen/drivers/char/serial.c | 69 +++++++++++++++++++++++++++++++++++++-- xen/include/xeno/serial.h | 7 ++++ 4 files changed, 74 insertions(+), 33 deletions(-) diff --git a/xen/arch/i386/pdb-stub.c b/xen/arch/i386/pdb-stub.c index 3f905b3f05..3184c7e629 100644 --- a/xen/arch/i386/pdb-stub.c +++ b/xen/arch/i386/pdb-stub.c @@ -32,11 +32,6 @@ void pdb_put_packet (unsigned char *buffer, int ack); int pdb_initialized = 0; static int pdb_serhnd = -1; -#define RX_SIZE 32 -#define RX_MASK(_i) ((_i)&(RX_SIZE-1)) -static unsigned int rx_cons = 0, rx_prod = 0; -static unsigned char rx_ring[RX_RING_SIZE]; - static inline void pdb_put_char(unsigned char c) { serial_putc(pdb_serhnd, c); @@ -44,15 +39,7 @@ static inline void pdb_put_char(unsigned char c) static inline unsigned char pdb_get_char(void) { - while ( rx_cons == rx_prod ) - barrier(); - return rx_ring[RX_MASK(rx_cons++)]; -} - -static void pdb_rx_char(unsigned char c, struct pt_regs *regs) -{ - if ( (rx_prod - rx_cons) != RX_SIZE ) - rx_ring[RX_MASK(rx_prod++)] = c; + return serial_getc(pdb_serhnd); } static volatile int mem_err = 0; @@ -844,8 +831,6 @@ void initialize_pdb() return; } - serial_set_rx_handler(pdb_serhnd, pdb_rx_char); - printk("Initialised pervasive debugger (PDB) on port %s\n", opt_pdb); /* Acknowledge any spurious GDB packets. */ diff --git a/xen/arch/i386/traps.c b/xen/arch/i386/traps.c index 00a8fd2b52..f71ce60d57 100644 --- a/xen/arch/i386/traps.c +++ b/xen/arch/i386/traps.c @@ -196,8 +196,6 @@ static inline void do_trap(int trapnr, char *str, trap_info_t *ti; unsigned long fixup; - __sti(); - if (!(regs->xcs & 3)) goto fault_in_hypervisor; @@ -259,8 +257,6 @@ asmlinkage void do_int3(struct pt_regs *regs, long error_code) struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id(); trap_info_t *ti; - __sti(); - if ( (regs->xcs & 3) != 3 ) { if ( pdb_handle_exception(3, regs) == 0 ) @@ -327,8 +323,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code) __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : ); - __sti(); - if ( unlikely(addr >= LDT_VIRT_START) && (addr < (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) ) { @@ -396,8 +390,6 @@ asmlinkage void do_general_protection(struct pt_regs *regs, long error_code) trap_info_t *ti; unsigned long fixup; - __sti(); - /* Badness if error in ring 0, or result of an interrupt. */ if ( !(regs->xcs & 3) || (error_code & 1) ) goto gp_in_kernel; @@ -506,8 +498,6 @@ asmlinkage void math_state_restore(struct pt_regs *regs, long error_code) /* Prevent recursion. */ clts(); - __sti(); - if ( !test_bit(PF_USEDFPU, ¤t->flags) ) { if ( test_bit(PF_DONEFPUINIT, ¤t->flags) ) @@ -532,8 +522,6 @@ asmlinkage void do_debug_orig(struct pt_regs *regs, long error_code) struct task_struct *tsk = current; struct guest_trap_bounce *gtb = guest_trap_bounce+smp_processor_id(); - __sti(); - __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); /* Mask out spurious debug traps due to lazy DR7 setting */ @@ -580,8 +568,6 @@ asmlinkage void do_debug(struct pt_regs *regs, long error_code) return; } - __sti(); - __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); if ( (condition & (1 << 14)) != (1 << 14) ) printk("\nwarning: debug trap w/o BS bit [0x%x]\n\n", condition); diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c index ff5d3d1e4c..ad8a4a2702 100644 --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -70,10 +70,14 @@ #define PARITY_MARK (5<<3) #define PARITY_SPACE (7<<3) +#define RXBUFSZ 32 +#define MASK_RXBUF_IDX(_i) ((_i)&(RXBUFSZ-1)) typedef struct { - int baud, data_bits, parity, stop_bits, io_base, irq; - serial_rx_fn rx_lo, rx_hi, rx; - spinlock_t lock; + int baud, data_bits, parity, stop_bits, io_base, irq; + serial_rx_fn rx_lo, rx_hi, rx; + spinlock_t lock; + unsigned char rxbuf[RXBUFSZ]; + unsigned int rxbufp, rxbufc; } uart_t; static uart_t com[2] = { @@ -103,6 +107,7 @@ static void uart_rx(uart_t *uart, struct pt_regs *regs) /* * No need for the uart spinlock here. Only the uart's own interrupt * handler will read from the RBR and the handler isn't reentrant. + * Calls to serial_getc() will disable this handler before proceeding. */ while ( inb(uart->io_base + LSR) & LSR_DR ) { @@ -113,6 +118,8 @@ static void uart_rx(uart_t *uart, struct pt_regs *regs) uart->rx_hi(c&0x7f, regs); else if ( !(c & 0x80) && (uart->rx_lo != NULL) ) uart->rx_lo(c&0x7f, regs); + else if ( (uart->rxbufp - uart->rxbufc) != RXBUFSZ ) + uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufp++)] = c; } } @@ -396,3 +403,59 @@ void serial_puts(int handle, const unsigned char *s) spin_unlock_irqrestore(&uart->lock, flags); } + +/* Returns TRUE if given character (*pc) matches the serial handle. */ +static int byte_matches(int handle, unsigned char *pc) +{ + if ( !(handle & SERHND_HI) ) + { + if ( !(handle & SERHND_LO) || !(*pc & 0x80) ) + return 1; + } + else if ( *pc & 0x80 ) + { + *pc &= 0x7f; + return 1; + } + return 0; +} + +unsigned char serial_getc(int handle) +{ + uart_t *uart = &com[handle & SERHND_IDX]; + unsigned char c; + unsigned long flags; + + spin_lock_irqsave(&uart->lock, flags); + + while ( uart->rxbufp != uart->rxbufc ) + { + c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)]; + if ( byte_matches(handle, &c) ) + goto out; + } + + disable_irq(uart->irq); + + /* disable_irq() may have raced execution of uart_rx(). */ + while ( uart->rxbufp != uart->rxbufc ) + { + c = uart->rxbuf[MASK_RXBUF_IDX(uart->rxbufc++)]; + if ( byte_matches(handle, &c) ) + goto enable_and_out; + } + + /* We now wait for the UART to receive a suitable character. */ + do { + while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 ) + barrier(); + c = inb(uart->io_base + RBR); + } + while ( !byte_matches(handle, &c) ); + + enable_and_out: + enable_irq(uart->irq); + out: + spin_unlock_irqrestore(&uart->lock, flags); + return c; +} diff --git a/xen/include/xeno/serial.h b/xen/include/xeno/serial.h index c24f0c665f..3640fd036f 100644 --- a/xen/include/xeno/serial.h +++ b/xen/include/xeno/serial.h @@ -36,4 +36,11 @@ void serial_putc(int handle, unsigned char c); /* Transmit a NULL-terminated string via the specified COM port. */ void serial_puts(int handle, const unsigned char *s); +/* + * An alternative to registering a character-receive hook. This function + * will not return until a character is available. It can safely be + * called with interrupts disabled. + */ +unsigned char serial_getc(int handle); + #endif /* __XEN_SERIAL_H__ */ -- 2.30.2